为什么需要会话回溯
OpenClaw 的会话不会自动消失,但也不会自动排队等你翻。日子久了,sidebar 里全是 main、cron:xxxx、group:xxxx,光看名字根本想不起哪次聊过「halo 主题 500 排障」。
粗暴办法是滚动聊天记录——但 cron 任务和子会话根本不在你眼前。正确姿势是用三个核心工具组成一条流水线:
- sessions_list —— 先拿到「有哪些会话」的清单(可过滤、可分页)。
- sessions_search —— 拿着关键词全文搜,直接命中某条消息。
- sessions_history —— 用搜到的
sessionKey/messageId把上下文原文读出来。
下面每一步的参数都来自本机 tool_describe 的真实返回,不编造。
第一步:sessions_list 列出并缩小范围
sessions_list 是「元数据-only」的清单,默认每条只返回 key、agentId、kind、channel、archived、pinned 等字段,不会把整段对话灌进来,所以先拿它做筛选最省 token。
常用过滤参数(均为可选):
kinds:数组,取值main/group/cron/hook/node/other。只想看定时任务就传["cron"]。
group/pinned:按自定义分组、是否钉置顶过滤。
agentId/workspaceDir/projectId:按智能体或工作区缩圈。
search:直接按会话标签/显示名做文本过滤(注意它搜的是元数据,不是消息正文;正文搜索交给下一步)。
activeOnly/activeMinutes:只看最近 N 分钟活跃过的。
includeLastMessage+messageLimit:把每条会话的最后几条消息预览也带回来,方便肉眼确认。
- 分页:
limit(默认 100,上限 200)+offset,用返回的hasMore/nextOffset继续翻。
一个真实例子:我只想翻「最近 7 天里,名字带 nginx 的会话」:
{
"search": "nginx",
"activeMinutes": 10080,
"includeLastMessage": true,
"messageLimit": 1
}
返回的每条 sessions 里有 key(后续 history 要用的 sessionKey)、derivedTitle(若开了 includeDerivedTitles)、lastMessagePreview。先凭这些锁定目标 key,再进第二步精搜。
实战踩坑提醒:relationship=owned|created|involving 是按「请求用户身份」筛的,没有可信用户身份时不可用。别在本机 agent 自己跑的时候指望它只给你自己的会话——默认它就是列出可见会话。
第二步:sessions_search 全文命中
sessions_list 的 search 只扫元数据,正文搜要靠 sessions_search。它返回的是「匹配到的消息片段」,每条带:
sessionKey/sessionId:定位用。
messageId:精确那一条。
snippet:命中上下文片段。
score:相关度。
role:user 还是 assistant。
参数就三个,都很克制:
query(必填,字符串,最长 4096):要搜的词,例如"nginx 反代 443"。
limit:结果条数,1–25,默认 10。
sessionKey:可选,限定只在某个会话里搜。
{
"query": "nginx 反代 证书",
"limit": 10
}
返回里如果某条 sessionId 非空,说明它来自某个具体 transcript。这时要带着 sessionId 去读 history(见下一步),否则只传 sessionKey 读最新尾部即可。
实战踩坑提醒:归档会话的 transcript 默认不进搜索(archivedTranscriptsExcluded会告诉你被排除几条)。要搜归档里的旧事,先确认它没被排除,或改用sessions_list带archived:"all"把归档行也列出来再针对性 history。
第三步:sessions_history 读原文上下文
拿到 sessionKey(+ 可选 messageId / sessionId)后,用 sessions_history 把真实对话读出来。它有几种读法:
- 只传
sessionKey:返回该会话最新尾部(limit默认几条,上限 1000)。
- 加
messageId:以那条消息为中心开窗,offset被忽略,limit约束窗口大小——最适合「搜到一条,看它前后在聊啥」。
- 加
sessionId:当messageId属于某个具体 transcript 时必须传,否则读最新尾部。
includeTools:把工具调用消息也带回来(排障时很有用,能看到当时跑了什么命令)。
offset:对未锚定的历史做普通分页;配hasMore/nextOffset往后翻。
{
"sessionKey": "agent:main:cron:6276...",
"messageId": "msg_01H...",
"limit": 20,
"includeTools": true
}
返回结构里有 messages(数组,元素结构由实现决定)、truncated / contentTruncated / contentRedacted(脱敏与截断标记)、bytes(体量)、pendingInputs(那些被接受但排在模型历史之外的输入)。排障时特别要看 contentRedacted —— 如果为 true,说明原文里有被遮盖的敏感内容,你拿到的不是全貌。
实战踩坑提醒:Cancelled/interrupted inputs never replay automatically。如果pendingInputs里某条是interrupted或cancelled状态,它不会自动重放,你得自己判断当时到底执行到哪一步。别以为 history 里「没看到」就等于「没发生」。
一条完整流水线串起来
把三步合起来,真实工作流是:
sessions_list(search:"nginx",includeLastMessage:true)→ 拿到候选key列表。
- 对最像的那个
key跑sessions_search(query:"反代 443",sessionKey:key)→ 命中messageId。
sessions_history(sessionKey:key,messageId:...,includeTools:true)→ 读出当时完整的排障对话和执行的命令。
这样你从「好像聊过 nginx」到「精确到那天的第几句话、跑了哪条 openssl 命令」,三步搞定,不用翻聊天框,也不用在几十个 cron 会话里盲找。
和其他记忆工具怎么选
- 想找「某次具体对话说了啥」→ 本文三件套(sessions_*)。
- 想找「我长期记住的偏好/决策」→
memory_search/memory_get(读 MEMORY.md、USER.md)。
- 想找「外部频道里的某段讨论」→
conversations_list/conversations_search。
- 想找「还没加载的工具怎么用」→
tool_search+tool_call。
分工很清楚:会话回溯管「对话现场」,记忆系统管「沉淀结论」。
小结
OpenClaw 的会话回溯不是靠人肉滚动,而是 sessions_list(列)→ sessions_search(搜)→ sessions_history(读)的三段式。关键记住三点:list 的 search 只扫元数据、正文搜交给 search 工具;history 读锚点消息要带 messageId(+ 必要时 sessionId);contentRedacted 和 pendingInputs 状态决定你拿到的是全貌还是残影。把这套用在「上周那次排障现在又要复现」的场景,效率直接拉满。
扫码关注公众号,获取更多 OpenClaw 实操技巧:
